package com.impression.chq.http;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * @author CHQ
 * @version 1.0
 * @date 创建时间： 2016/12/3 16:45
 * @parameter
 * @return
 * 参考：http://blog.csdn.net/itachi85/article/details/51142486
 */
public class OkHttpEngine {

    public static final String TAG="debug-okhttp";
    public static final boolean isDebug = true;
    public static final int TIMEOUT = 20;

    private static OkHttpEngine mInstance = null;
    private OkHttpClient mOkHttpClient;
    private OkHttpClient.Builder mOkHttpClientBilder;
    private Call mCall;
    private Handler mHandler = new Handler(Looper.getMainLooper());;

    public static OkHttpEngine getInstance() {
        if(mInstance == null) {
            synchronized (OkHttpEngine.class) {
                if(mInstance == null) {
                    mInstance = new OkHttpEngine();
                }
            }
        }
        return  mInstance;
    }

    //自定义构造函数
    private OkHttpEngine() {
        // 设置超时时间
        mOkHttpClientBilder = new OkHttpClient.Builder()
                .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS);
        //创建OkHttpClient对象
        mOkHttpClient = mOkHttpClientBilder.build();
    }

    //定义post Requset
    public void initRequest(RequestBody body, String url){
        Request request = new Request.Builder().url(url).post(body).build();
        mCall = mOkHttpClient.newCall(request);
    }

    //普通get请求
    public void getAsynHttp(String url, final ResultCallback callback){
        Request request = new Request.Builder().url(url).build();
        setStart(callback);
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                setError(callback,call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                setSuccess(callback,response.body().string());
            }
        });
    }

    //post请求（map为body）
    public void postAsynHttp(String url, Map<String,String> map, final ResultCallback callback){
        //创建请求的参数body
        FormBody.Builder builder = new FormBody.Builder();
        //遍历key
        for(Map.Entry<String,String> entry: map.entrySet()){
            String key = entry.getKey();
            String value = entry.getValue();
            debugParam(key,value);
            builder.add(key,value);
        }
        RequestBody body = builder.build();
        Request request = new Request.Builder().url(url).post(body).build();
        setStart(callback);
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                setError(callback,call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                setSuccess(callback,response.body().string());
            }
        });
    }

    //post请求(Json为Body)
    public void postJson(String url, String json, final ResultCallback callback){
        //创建请求的参数body
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON,json);
        Request request = new Request.Builder().url(url).post(body).build();
        setStart(callback);
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                setError(callback,call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                setSuccess(callback,response.body().string());
            }
        });
    }

    //post上传文件(带参数)
    public void postAsynFiles(String url, Map<String,String> map , Map<String,String> files, final ResultCallback callback){
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);     //form表单
        //遍历参数
        if(map != null){
            for(Map.Entry<String,String> entry: map.entrySet()){
                String key = entry.getKey();
                Object value = entry.getValue();
                builder.addFormDataPart(key,value.toString());
            }
        }

        MediaType mediaType = MediaType.parse("image/png");
        //遍历文件
        for(Map.Entry<String,String> entry: files.entrySet()){
            String filename = entry.getKey();
            String fileUrl = entry.getValue();
            //这里“file”只是一个标志，不影响多文件上传
            builder.addFormDataPart("file", filename ,RequestBody.create(mediaType,new File(fileUrl)));
        }
        RequestBody body = builder.build();
        Request request = new Request.Builder().url(url).post(body).build();
        setStart(callback);
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                setError(callback,call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                setSuccess(callback,response.body().string());
            }
        });
    }


    /**
     * 下载文件保存到本地
     * @param url
     * @param filePath
     * @param callback
     */
    public void downAsynFile(String url, final String filePath , final ResultCallback callback) {
        Request request = new Request.Builder().url(url).build();
        setStart(callback);
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //sendFailedCallback(call,e,callback);
            }

            @Override
            public void onResponse(Call call, Response response) {
                InputStream inputStream = response.body().byteStream();
                FileOutputStream fileOutputStream = null;
                try {
                    fileOutputStream = new FileOutputStream(new File(filePath));
                    byte[] buffer = new byte[2048];
                    int len = 0;
                    while ((len = inputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, len);
                    }
                    fileOutputStream.flush();
                    setSuccess(callback,response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                    setError(callback,call,e);
                }
            }
        });
    }

    //取消请求
    public boolean cancelRequest(){
        if(!mCall.isCanceled()){
            mCall.cancel();
            return true;       //取消成功
        }
        return false;     //取消失败
    }


    //开始时，执行这个方法
    private void setStart(final ResultCallback callback){
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onStart();
            }
        });
    }

    //失败之后就执行这个回调
    private void setError(final ResultCallback callback,final Call call,final IOException e){
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onError(call,e);
            }
        });
    }

    //成功之后就执行这个回调
    private void setSuccess(final ResultCallback callback, final String data){
        debugResponse(data);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    callback.onSuccess(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * log信息打印
     * @param params
     */
    public void debugResponse(String params){
        if(!isDebug){
            return;
        }
        if(null == params){
            Log.d(TAG, "params is null");
        }else{
            Log.d(TAG, params);
        }
    }

    public void debugParam(String key,String value){
        if(!isDebug){
            return;
        }
        Log.d(TAG, "key = "+key+", value ="+value);
    }

}
